package com.hddf.project.upload_cache;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.kommii.common_utils.DateTime_Utils;
import org.kommii.mongodb.Mongodb_ConnPools;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

public class CacheService {
	private static String padding = "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "..................................................................................................................................................................."
			+ "...................................................................................................................................................................";
	private static List<String> empty = new ArrayList<String>();
	public static String IMGS_TYPE = "imgs";
	public static String DOCS_TYPE = "docs";
	public static String TABLES_TYPE = "tables";
	public static String APPROVAL_TYPE = "approval";
	public static String CHECKS_TYPE = "checks";
	public static String PATH_PARAM = "path";
	public static String USER_ID = "user_id";
	public static String VIDEO_TYPE = "video";
	public static String OTHER_TYPE = "other";
	private static CacheService cache_service = null;
	private static CacheDaoImpl_MongoDB cacheDao_MongoDB = null;
	private static String ROOTPATH = " abcdefg123";
	static {
		if (cache_service == null) {
			cache_service = new CacheService();
		}
		if (cacheDao_MongoDB == null) {
			cacheDao_MongoDB = new CacheDaoImpl_MongoDB();
		}
	}

	public static CacheService getInstance() {
		return cache_service;
	}

	/**
	 * 根据 _id 获取upload cache
	 * 
	 * @param id
	 * @return
	 */
	public DBObject getObjById(String id) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			return cacheDao_MongoDB.getObjById(id, coll);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 添加一个空的upload cache
	 * 
	 * @param user_id
	 *            用户id
	 * @return 返回一个ObjectId
	 */
	public String addObj(int user_id) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			BasicDBObject entity = new BasicDBObject();
			entity.put("user_id", user_id);
			entity.put("path", "");
			entity.put("imgs", empty);
			entity.put("tables", empty);
			entity.put("checks", empty);
			entity.put("docs", empty);
			entity.put("approval", empty);
			entity.put("padding", padding);
			entity.put("video", empty);
			entity.put("other", empty);
			return cacheDao_MongoDB.save(entity, coll);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 检验某个数组中是否已经存在某个文件
	 * 
	 * @param id
	 *            ObjectId
	 * @param type
	 *            数组类型(数组名)
	 * @param fileName
	 *            要查询的文件名
	 * @return 存在则返回文件名:::文件上传后的路径；不存在则返回空
	 */
	public String isFileExist(String id, String type, String fileName) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			DBObject obj = cacheDao_MongoDB.getObjById(id, coll);
			BasicDBList arr = (BasicDBList) obj.get(type);

			String temp = null;
			boolean b = false;
			for (int i = 0; i < arr.size(); i++) {
				temp = (String) arr.get(i);
				b = temp.startsWith(fileName);
				if (b)
					break;
			}
			if (b)
				return temp;
			else
				return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 检验某个数组中是否已经存在一个或者多个文件
	 * 
	 * @param id
	 *            ObjectId
	 * @param type
	 *            数组类型(数组名)
	 * @param fileName
	 *            要查询的文件名
	 * @return
	 */
	public List<String> isFileExist(String id, String type, List<String> files) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			DBObject obj = cacheDao_MongoDB.getObjById(id, coll);
			BasicDBList arr = (BasicDBList) obj.get(type);
			List<String> list = new ArrayList<String>();
			String temp = null;
			boolean b = false;
			int size = 0;
			String fileName = null;
			if (null != files) {
				size = files.size();
			}
			for (int j = 0; j < size; j++) {
				fileName = files.get(j);
				for (int i = 0; i < arr.size(); i++) {
					temp = (String) arr.get(i);
					b = temp.startsWith(fileName);
					if (b) {
						list.add(temp);
						break;
					}
				}
				b = false;
			}
			if (list.size() != 0)
				return list;
			else
				return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 修改 路径上传文档所在的路径 path
	 * 
	 * @param id
	 *            ObjectId
	 * @param path
	 *            路径
	 * @return
	 */
	public boolean updatePath(String id, String path) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			BasicDBObject doc = new BasicDBObject();
			doc.put("_id", id);
			BasicDBObject o = new BasicDBObject();
			o.put("path", path);
			doc.put("$set", o);
			boolean rs = cacheDao_MongoDB.update(doc, coll);
			return rs;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 修改对应的数组 imgs docs checks tables approval
	 * 
	 * @param id
	 *            ObjectId
	 * @param type
	 * @param value
	 * @return
	 */
	public boolean update(String id, String type, List<String> value) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			BasicDBObject doc = new BasicDBObject();
			doc.put("_id", id);

			// 消除站位的padding
			BasicDBObject o1 = new BasicDBObject();
			o1.put("padding", 1);
			doc.put("$unset", o1);

			// 修改对应的数组 imgs docs checks tables approval
			BasicDBObject o2 = new BasicDBObject();
			o2.put("$each", value);
			BasicDBObject o3 = new BasicDBObject();
			o3.put(type, o2);
			doc.put("$addToSet", o3);
			boolean rs = cacheDao_MongoDB.update(doc, coll);
			return rs;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 删除数组中的某个元素 (imgs docs checks tables approval)
	 * 
	 * @param id
	 *            ObjectId
	 * @param type
	 * @param value
	 * @return
	 */
	public boolean deleteArrayItem(String id, String type, String value) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			BasicDBObject doc = new BasicDBObject();
			doc.put("_id", id);

			// 删除数组中的某个元素 imgs docs checks tables approval
			BasicDBObject o = new BasicDBObject();
			o.put(type, value);
			doc.put("$pull", o);
			boolean rs = cacheDao_MongoDB.update(doc, coll);
			return rs;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/*
	 * public boolean update(String id ,String type , Map<String,String> value){
	 * DBCollection coll = null; try{ coll =
	 * Mongodb_ConnPools.getMongoDB_Coll("cache"); BasicDBObject doc = new
	 * BasicDBObject(); doc.put("_id", id); BasicDBObject o = new
	 * BasicDBObject(); //消除站位的padding BasicDBObject o1 = new BasicDBObject();
	 * o1.put("padding", 1); //BasicDBObject o2 = new BasicDBObject();
	 * doc.put("$unset", o1); //修改对应的数组 imgs docs checks tables approval
	 * BasicDBObject o4 = new BasicDBObject(); o4.put(type, value);
	 * //BasicDBObject o5 = new BasicDBObject(); //doc.put("$push", o4);
	 * doc.put("$addToSet", o4); boolean rs = cacheDao_MongoDB.update(doc,
	 * coll); return rs; }catch(Exception e){ e.printStackTrace(); return false;
	 * } }
	 */

	/**
	 * 通过 _id 删除一条数据
	 * 
	 * @param id
	 * @return
	 */
	public boolean deleteById(String id) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			return cacheDao_MongoDB.delete(id, coll);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 通过 user_id 删除一条或多条数据
	 * 
	 * @param uid
	 *            用户id
	 * @return
	 */
	public int deleteByUserId(int uid) {
		DBCollection coll = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			return cacheDao_MongoDB.deleteByUserId(uid, coll);
		} catch (Exception e) {
			e.printStackTrace();
			return -1;
		}
	}

	/**
	 * 删除过期的缓存;删除无效的上传文件以及mongodb中的缓存数据
	 * 
	 * @param rootPath
	 *            文件所在的根路径 例如 /home/upload/
	 */
	public void removeOverdueCache() {
		DBCollection coll = null;
		DBCollection coll2 = null;
		try {
			coll = Mongodb_ConnPools.getMongoDB_Coll("uploadcache", "cache");
			coll2 = Mongodb_ConnPools.getMongoDB_Coll("store_auth", "user");
			DBCursor cursor = cacheDao_MongoDB.getCollCursor(coll);
			DBObject obj = null;
			DBObject obj2 = null;
			Set<Integer> set = new HashSet<Integer>();
			List<String> fileList = new ArrayList<String>();
			while (cursor.hasNext()) {
				obj = cursor.next();
				int uid = (Integer) obj.get("user_id");
				String path = (String) obj.get("path");
				// System.out.println(uid);
				long lifetime = 0;
				obj2 = cacheDao_MongoDB.getUserWebtoken_lifetime(uid, coll2);
				if (null != obj2)
					lifetime = (Long) obj2.get("webtoken_lifetime");
				long current = DateTime_Utils.getCurrentSeconds();
				if (current - lifetime > 0) {
					set.add(uid);
					fileList.add(path);
				}
			}
			for (String str : fileList) {
				deleteDirectory(str, ROOTPATH);
			}
			int rs = cacheDao_MongoDB.deleteByUserIdSet(set, coll);
			// System.out.println("delete : " + rs);
			return;
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
	}

	/**
	 * 删除文件夹,以及其子目录与子目录中的文件
	 * 
	 * @param sPath
	 * @return
	 */
	public static boolean deleteDirectory(String sPath, String rootPath) {
		boolean flag = false;
		if (null == sPath || !sPath.startsWith(rootPath)) {
			return false;
		}
		// 如果sPath不以文件分隔符结尾，自动添加文件分隔符
		if (!sPath.endsWith(File.separator)) {
			sPath = sPath + File.separator;
		}
		File dirFile = new File(sPath);
		// 如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			return false;
		}
		flag = true;
		// 删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			// 删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath(), rootPath);
				if (!flag)
					break;
			} // 删除子目录
			else {
				flag = deleteDirectory(files[i].getAbsolutePath(), rootPath);
				if (!flag)
					break;
			}
		}
		if (!flag)
			return false;
		// 删除当前目录
		if (dirFile.delete()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 删除某个文件
	 * 
	 * @param sPath
	 * @return
	 */
	public static boolean deleteFile(String sPath, String rootPath) {
		boolean flag = false;
		if (null == sPath || !sPath.startsWith(rootPath)) {
			return false;
		}
		File file = new File(sPath);
		// 路径为文件且不为空则进行删除
		if (file.isFile() && file.exists()) {
			file.delete();
			flag = true;
		}
		return flag;
	}

	public static void setRootPath(String rootPath) {
		CacheService.ROOTPATH = rootPath;
	}

}
